#include "keylogger.h"

KKeylogger::KKeylogger(int *startWorkTimestamp, int *stopWorkTimestamp)
{
	*startWorkTimestamp = -1;
	*stopWorkTimestamp = -1;
	m_userData.startWorkTimestamp = startWorkTimestamp;
	m_userData.stopWorkTimestamp = stopWorkTimestamp;
}

KKeylogger::~KKeylogger()
{
}

void KKeylogger::start()
{
	if (!XRecordEnableContext(m_userData.dataDisplay, m_recordContext, eventCallback, (XPointer)&m_userData))
	{
		throw runtime_error("enable context failed");
	}
}

void KKeylogger::setupRecordExtension()
{
	int majorVersion;
	int minorVersion;

	if (!XRecordQueryVersion(m_userData.ctrlDisplay, &majorVersion, &minorVersion))
	{
		throw runtime_error("version query failed");
	}
	
	m_recordClientSpec = XRecordAllClients;
	m_recordRange = XRecordAllocRange();

	if (!m_recordRange)
	{
		throw runtime_error("record range alloc failed");
	}

	m_recordRange->device_events.first = KeyPress;
	m_recordRange->device_events.last = ButtonPress;
	
	m_recordContext = XRecordCreateContext(m_userData.dataDisplay, 0, &m_recordClientSpec, 1, &m_recordRange, 1);

	if (!m_recordContext)
	{
		throw runtime_error("record context is null");
	}
}

bool KKeylogger::xConnect(const std::string &displayName)
{
	if (NULL == (m_userData.ctrlDisplay = XOpenDisplay(displayName.c_str())))
		return false;

	if (NULL == (m_userData.dataDisplay = XOpenDisplay(displayName.c_str())))
	{
		XCloseDisplay (m_userData.ctrlDisplay);
		m_userData.ctrlDisplay = NULL;
		return false;
	}

	cout << "control display and data display created" << endl;
	setupRecordExtension();
	return true;
}

void KKeylogger::processData()
{
	XRecordProcessReplies(m_userData.dataDisplay);
}

void KKeylogger::eventCallback(XPointer priv, XRecordInterceptData *hook)
{
	if (hook->category != XRecordFromServer)
	{
		XRecordFreeData(hook);
		return;
	}

	XRecordDatum *data = (XRecordDatum *)hook->data;

	CallbackClosure *datum = (CallbackClosure *)priv;

	*(datum->stopWorkTimestamp) = time(0);

	if (*(datum->startWorkTimestamp) == -1)
		*(datum->startWorkTimestamp) = *(datum->stopWorkTimestamp);


	XRecordFreeData(hook);
}
